package com.bolt.support.spring.jpa.transform;

import com.bolt.common.bean.BeanUtil;
import com.bolt.common.reflect.ClassUtil;
import com.bolt.common.utils.StrUtil;
import com.bolt.support.sqlconfig.base.SQLConfiguration;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.transform.ResultTransformer;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;

public class BeanMapperTransform implements ResultTransformer {

    protected final Log logger = LogFactory.getLog(getClass());

    private final Class<?> returnType;

    private final SQLConfiguration configuration;


    private Map<String, PropertyDescriptor> propertyDescriptorMap;


    public BeanMapperTransform(Class<?> returnType, SQLConfiguration configuration) {
        if (returnType == null) throw new IllegalArgumentException("resultClass cannot be null");
        this.returnType = returnType;
        try {
            this.propertyDescriptorMap = BeanUtil.getPropertyDescriptorMap(this.returnType, true);
        } catch (IntrospectionException e) {
            logger.warn("bean mapper error", e);
        }
        this.configuration = configuration;
    }

    @Override
    public Object transformTuple(Object[] result, String[] aliases) {

        return beanMapper(result, aliases);
    }

    private Object beanMapper(Object[] result, String[] aliases) {
        Object beanMapper = ClassUtil.newInstance(this.returnType);

        for (int i = 0; i < aliases.length; i++) {
            String alias = StrUtil.toCamelCase(aliases[i]);
            if (StrUtil.isBlank(alias)) {
                continue;
            }
            Object value = result[i];
            PropertyDescriptor propertyDescriptor = this.propertyDescriptorMap.get(alias);
            if (propertyDescriptor == null) {
                continue;
            }
            try {
                Method method = propertyDescriptor.getWriteMethod();
                value = configuration.getTypeConverterRegistry().convert(propertyDescriptor.getPropertyType(), value);
                method.invoke(beanMapper, value);
            } catch (IllegalAccessException e) {
                logger.warn("bean mapper error", e);
            } catch (InvocationTargetException e) {
                logger.warn("bean mapper error", e);
            }
        }
        return beanMapper;
    }


    @Override
    public List transformList(List collection) {
        return collection;
    }
}

 